package cn.getech.data.development.service.impl;

import cn.getech.data.development.constant.RunStatus;
import cn.getech.data.development.entity.*;
import cn.getech.data.development.mapper.RealTimeTaskMenuMapper;
import cn.getech.data.development.model.dto.RealTimeTaskMenuSaveDto;
import cn.getech.data.development.model.vo.*;
import cn.getech.data.development.service.*;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.getech.data.intelligence.common.utils.Constant;
import cn.getech.data.intelligence.common.utils.PojoUtils;
import cn.getech.data.intelligence.common.utils.R;
import cn.getech.system.center.service.SysUserRoleService;
import cn.getech.system.center.utils.ShiroUtils;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RealTimeTaskMenuServiceImpl extends ServiceImpl<RealTimeTaskMenuMapper, RealTimeTaskMenu> implements RealTimeTaskMenuService {

    @Resource
    private RealTimeTaskMenuMapper mapper;
    @Resource
    private ProcInfoService procInfoService;
    @Autowired
    private RealTimeTaskLogService realTimeTaskLogService;
    @Autowired
    private RealTimeTaskService realTimeTaskService;
    @Autowired
    private IBdpRealTaskAlarmObjectService iBdpRealTaskAlarmObjectService;
    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Override
    public R saveOrUpdate(RealTimeTaskMenuSaveDto dto) {
        if (dto.getId() == null && dto.getLevel() == null) {
            return R.error("目录级别不能为空！");
        }
        if (dto.getLevel() != null && dto.getMenuType() != null) {
            if (dto.getLevel() > 3 && dto.getMenuType() == 1) {
                return R.error("目录级别不能大于3级！");
            }
        }
        // 判断同一目录下是否存在同名目录
        QueryWrapper<RealTimeTaskMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", dto.getParentId());
        wrapper.eq("name", dto.getName());
        wrapper.eq("proc_id", dto.getProcId());
        wrapper.eq("state", Constant.StateEnum.ENABLE.getValue());
        if (mapper.selectCount(wrapper) > 0) {
            return R.error("已存在同名目录！");
        }
        try {
            RealTimeTaskMenu entity = new RealTimeTaskMenu();
            BeanUtils.copyProperties(dto, entity);

            entity.setUpdatePer(ShiroUtils.getUserId().intValue());
            int logType = 0;
            int count = 0;
            if (entity.getId() != null) {
               count = mapper.updateById(entity);
                logType = cn.getech.data.development.constant.Constant.RealTimeTaskLogType.UPDATE.getCode();
            }else {
                entity.setCreatePer(entity.getUpdatePer());
                count = mapper.insert(entity);
                logType = cn.getech.data.development.constant.Constant.RealTimeTaskLogType.CREATE.getCode();
                // 创建任务表
                RealTimeTask task = new RealTimeTask();
                task.setMenuId(entity.getId());
                if (dto.getTaskType() == null) {
                    dto.setTaskType(cn.getech.data.development.constant.Constant.RealTimeTaskType.FLINK.getCode());
                }
                task.setTaskType(dto.getTaskType());
                task.setUpdatePer(ShiroUtils.getUserId().intValue());
                task.setUpdateTime(new Date());
                realTimeTaskService.save(task);
            }
            if (count > 0) {
                // 保存操作日志
                RealTimeTaskLog log = new RealTimeTaskLog();
                log.setTaskId(entity.getId());
                log.setType(logType);
                log.setOperationPer(ShiroUtils.getUserId().intValue());
                realTimeTaskLogService.save(log);

                RealTimeTaskMenuSearchVO vo = new RealTimeTaskMenuSearchVO();
                vo.setId(entity.getId());
                List<RealTimeTaskMenuVO> menuList = mapper.menuList(vo);
                if (CollectionUtil.isNotEmpty(menuList)) {
                    return R.okWithData(menuList.get(0));
                }
            }
        }catch (Exception e){
            log.error("保存实时任务目录出错：{}", e);
        }
        return R.error("保存实时任务目录失败！");
    }

    @Override
    public R deleteMenu(Integer id) {
        try {
            RealTimeTaskMenu realTimeTaskMenu = mapper.selectById(id);
            if (realTimeTaskMenu == null) {
                return R.error("找不到记录！");
            }
            RealTimeTaskVO vo = realTimeTaskService.getByMenuId(id);
            if (RunStatus.RUNNING.getStatus().equals(vo.getRunState())) {
                return R.error("当前任务正在运行，不可删除");
            }
            ProcInfo procInfo = procInfoService.getById(realTimeTaskMenu.getProcId());
            if (procInfo == null) {
                return R.error("项目不存在！");
            }
            List<BdpRealTaskAlarmObject> objectList = iBdpRealTaskAlarmObjectService.list(new QueryWrapper<BdpRealTaskAlarmObject>().eq("object_id", id));
            if(CollectionUtil.isNotEmpty(objectList)){
                return R.error("当前实时任务有关联到实时任务告警,请先删除对应的实时任务告警！");
            }
            if (realTimeTaskMenu.getCreatePer().intValue() != ShiroUtils.getUserId().intValue()
                    && procInfo.getCreatePer().intValue() != ShiroUtils.getUserId().intValue()) {
                return R.error("您没有删除的权限！");
            }
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("parent_id", id);
            wrapper.eq("state",1);
            if (mapper.selectCount(wrapper) > 0){
                return R.error("当前目录非空，不允许删除!");
            }
            RealTimeTaskMenu update = new RealTimeTaskMenu();
            update.setUpdatePer(ShiroUtils.getUserId().intValue());
            update.setId(id);
            update.setState(Constant.StateEnum.DISABLE.getValue());
            if (mapper.updateById(update) <= 0) {
                return R.error("删除失败，请检查参数！");
            }
            return R.ok();
        }catch (Exception e){
            log.error("删除实时任务目录出错：{}", e.getMessage());
        }
        return R.error("删除实时任务目录出错！");
    }

    @Override
    public List<RealTimeTaskMenuVO> menuList(RealTimeTaskMenuSearchVO vo) {
        List<RealTimeTaskMenuVO> menuList = mapper.menuList(vo);
        if (CollectionUtil.isEmpty(menuList)) {
            return new ArrayList<>();
        }
        //得到对应的数据
        List<RealTimeTaskMenuVO> restList = null;
        try {
            restList = changeTreePack(PojoUtils.listConvert(RealTimeTaskMenuVO.class, menuList), false,true);
        } catch (IllegalAccessException e) {
            log.error("获取工作流菜单树异常，error:{}", e.getMessage());
            throw new RRException("获取工作流菜单树异常！");
        }
        return restList;
    }

    @Override
    public IPage<RealTimeTaskOpsVO> pageList(Page page, RealTimeTaskMenuSearchVO params) {
        return mapper.pageList(page, params);
    }

    @Override
    public List<ProcInfo> procs(Long userId, Integer tenantId) {
        if(sysUserRoleService.superAdmin(userId)){
            return mapper.procs(userId,null);
        }else{
            return mapper.procs(userId,tenantId);
        }
    }

    @Override
    public List<IdAndNameVO> listByProcIdAndType(RealTaskTypeMenuSearchVO vo) {
        return mapper.listByProcIdAndType(vo.getProcId(),vo.getTaskType());
    }

    @Override
    public List<Long> listUserIds(Long userId, Integer tenantId) {
        if(sysUserRoleService.superAdmin(userId)){
            return mapper.listUserIds(null, tenantId);
        }else{
            return mapper.listUserIds(userId, null);
        }

    }

    private List<RealTimeTaskMenuVO> changeTreePack(List<RealTimeTaskMenuVO> listConvert, boolean subWorkFlow, boolean subNode) throws IllegalAccessException {
        String childrenFieldName = "children";

        // 获取根节点，即找出父节点为0或者为空对象
        List<RealTimeTaskMenuVO> topList = new ArrayList<>();
        topList = listConvert.stream().filter(workMenuDto -> Objects.equals(0, workMenuDto.getParentId().intValue())).collect(Collectors.toList());

        // 将根节点从原始list移除，减少下次处理数据
        listConvert.removeAll(topList);

        // 递归封装树
        fillTree(topList, listConvert, childrenFieldName, subWorkFlow,subNode);

        return topList;
    }

    private void fillTree(List<RealTimeTaskMenuVO> topList, List<RealTimeTaskMenuVO> listConvert, String childrenFieldName, boolean subWorkFlow,boolean subNode) throws IllegalAccessException {
        for (int i = 0; i < topList.size(); i++) {
            RealTimeTaskMenuVO parent = topList.get(i);
            //如果节点类型是2：任务（没有下级结构）
            if (parent.getMenuType() == 2) {
                continue;
            }
            List<RealTimeTaskMenuVO> children = fillChildren(parent, listConvert, childrenFieldName, subWorkFlow,subNode);
            if (children.isEmpty()) {
                continue;
            }
//            children = children.stream().filter(vo -> Objects.equals(children.get, 0)).collect(Collectors.toList());
//            if (null == children || children.isEmpty()) {
//                continue;
//            }
            parent.setChildList(children);
            listConvert.removeAll(children);
            fillTree(children, listConvert, childrenFieldName, subWorkFlow,subNode);
        }
    }

    private List<RealTimeTaskMenuVO> fillChildren(RealTimeTaskMenuVO parent, List<RealTimeTaskMenuVO> listConvert, String childrenFieldName, boolean subWorkFlow,boolean subNode) throws IllegalAccessException {
        List<RealTimeTaskMenuVO> childList = new ArrayList<>();
        Integer id = parent.getId();

        for (int i = 0; i < listConvert.size(); i++) {
            RealTimeTaskMenuVO t = listConvert.get(i);
            Integer childParentId = t.getParentId();
            if (id.equals(childParentId)) {
                childList.add(t);
            }
        }
//        if (!childList.isEmpty()) {
//            FieldUtils.writeDeclaredField(parent, childrenFieldName, childList, true);
//        }
        return childList;
    }


}
